#pragma once

#include "LvDevice.hpp"
#include "LvUtils.h"
#include "LvBuffer.hpp"

#include <memory>
#include <vector>

class LvModel
{
public:
	struct Vertex
	{
		glm::vec3 position{};
		glm::vec3 color{};
		glm::vec3 normal{};
		glm::vec2 uv{};

		static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
		static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();

		bool operator==(const Vertex& other) const
		{
			return position == other.position && color == other.color
				&& normal == other.normal && uv == other.uv;
		}
	};

	struct Builder
	{
		std::vector<Vertex> vertices{};
		std::vector<uint32_t> indices{};

		void loadModel(const std::string& filepath);
	};

	LvModel(LvDevice& device, const Builder& builder);
	~LvModel();

	LvModel(const LvModel&) = delete;
	LvModel& operator=(const LvModel&) = delete;


	static std::unique_ptr<LvModel> createModelFromFile(LvDevice& device, const std::string& filepath);

	void bind(VkCommandBuffer commandBuffer);
	void draw(VkCommandBuffer commandBuffer);

private:
	void createVertexBuffers(const std::vector<Vertex>& vertices);
	void createIndexBuffers(const std::vector<uint32_t>& indices);

	LvDevice& lvDevice;

	std::unique_ptr<LvBuffer> vertexBuffer;
	uint32_t vertexCount { 0 };

	std::unique_ptr<LvBuffer> indexBuffer;
	uint32_t indexCount{ 0 };
};

